package com.hyt.it.ogt.pj.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.hyt.it.ogt.pj.mapper.*;
import com.hyt.it.ogt.pj.model.entity.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.it.ogt.pj.enums.CommonEnums;
import com.hyt.it.ogt.pj.common.Constants;
import com.hyt.it.ogt.pj.common.ResponseCode;
import com.hyt.it.ogt.pj.enums.AutoFlagEnums;
import com.hyt.it.ogt.pj.enums.MarkTypeEnums;
import com.hyt.it.ogt.pj.enums.MarkmodelEnums;
import com.hyt.it.ogt.pj.model.param.ExamExpertSettingParam;
import com.hyt.it.ogt.pj.model.vo.ExamExpertSettingVo;
import com.hyt.it.ogt.pj.model.vo.ExamExpertVo;
import com.hyt.it.ogt.pj.model.vo.ExpertTreeVo;
import com.hyt.it.ogt.pj.model.vo.ExpertUserVo;
import com.hyt.it.ogt.pj.model.vo.ModeExamExpertVo;
import com.hyt.it.ogt.pj.model.vo.TaskNumberVo;
import com.hyt.it.ogt.pj.service.IExamExpertService;
import com.hyt.it.ogt.pj.utils.TreeUtil;
import com.hyt.loginfo.model.OfficeUserVO;
import com.hyt.loginfo.model.Tree;
import com.hyt.loginfo.model.param.OfficeUserPageParam;
import com.hyt.loginfo.service.IUaDeptService;


/**
 * <p>
 * 评卷专家 服务实现类
 * </p>
 *
 * @author liy
 * @since 2022-02-28
 */
@Service
public class ExamExpertServiceImpl extends BaseServiceImpl<ExamExpertMapper,ExamExpert> implements IExamExpertService {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ProjectSettingMapper projectSettingMapper;

    @Autowired
    private ModeExpertMapper modeExpertMapper;

    @Autowired
    private ExamExpertMapper examExpertMapper;

    @Autowired
    private PieceScoreMapper pieceScoreMapper;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private IUaDeptService uaDeptService;

    @Autowired
    private TeacherTaskInfoMapper teacherTaskInfoMapper;

    @Autowired
    private ItemScoreMapper itemScoreMapper;

    @Autowired
    private ProjectMapper projectMapper;

    @Override
    public ExamExpertSettingVo queryExamExpertSettingVo(ExamExpertSettingParam examExpertSettingParam) {
        ExamExpertSettingVo examExpertSettingVo = new  ExamExpertSettingVo();

        QueryWrapper<ProjectSetting> wrapper =  new QueryWrapper<>();
        wrapper.lambda().eq(ProjectSetting :: getProjectId,examExpertSettingParam.getProjectId());
        List<ProjectSetting> projectSettings = projectSettingMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(projectSettings)){
            examExpertSettingVo.setMarkType(projectSettings.get(0).getMarkType());
        }
        examExpertSettingVo.setProjectId(examExpertSettingParam.getProjectId());

        if(StringUtils.isNotEmpty(examExpertSettingParam.getModeExpertId())){
            ModeExpert modeExpert = modeExpertMapper.selectById(examExpertSettingParam.getModeExpertId());
            if(null != modeExpert){
                examExpertSettingVo.setAutoFlag(modeExpert.getAutoFlag());
                examExpertSettingVo.setNumber(modeExpert.getNumber());
            }
        }
        examExpertSettingVo.setModeExpertId(examExpertSettingParam.getModeExpertId());
        QueryWrapper<ExamExpert> examExpertWrapper =  new QueryWrapper<>();
        examExpertWrapper.lambda().eq(ExamExpert :: getProjectId,examExpertSettingParam.getProjectId())
                .eq(ExamExpert :: getModeExpertId,examExpertSettingParam.getModeExpertId())
                .orderByDesc(ExamExpert :: getUpdateDate);
        List<ExamExpert> examExperts = examExpertMapper.selectList(examExpertWrapper);
        //设置专家的已评卷数
        List<TaskNumberVo> taskNumberVos = taskMapper.queryFinishTaskPieceScore(examExpertSettingParam.getProjectId());

        if(!CollectionUtils.isEmpty(examExperts)){
            List<ExamExpertVo> examExpertVos = new ArrayList<>(examExperts.size());
            for (ExamExpert  examExpert :examExperts) {
                ExamExpertVo examExpertVo = new ExamExpertVo();
                BeanUtils.copyProperties(examExpert,examExpertVo);
                examExpertVos.add(examExpertVo);
            }
            examExpertSettingVo.setExamExpertVos(examExpertVos);
        }


        LambdaQueryWrapper<Task> taskWrapper =  new LambdaQueryWrapper<Task>();
        taskWrapper.eq(Task::getProjectId, examExpertSettingParam.getProjectId());
        if(MarkmodelEnums.MARK_MODEL_SUBJECT.getCode().equals(examExpertSettingParam.getMarkModel())
                && StringUtils.isNotEmpty(examExpertSettingParam.getSubjectId())){
            taskWrapper.eq(Task :: getSubjectId, examExpertSettingParam.getSubjectId());
            //处理已评卷量逻辑
            Map<String,List<TaskNumberVo>> taskNumberMap = taskNumberVos.stream().collect(Collectors.groupingBy(c -> c.getExpertId() + c.getSubjectId()));
            if(CollectionUtils.isNotEmpty(examExpertSettingVo.getExamExpertVos()) && MapUtils.isNotEmpty(taskNumberMap)){
                for (ExamExpertVo  examExpertVo :examExpertSettingVo.getExamExpertVos()) {
                    if(CollectionUtils.isEmpty(taskNumberMap.get(examExpertVo.getExpertId() + examExpertSettingParam.getSubjectId()))){
                        continue;
                    }
                    examExpertVo.setAlreadyQuantity(taskNumberMap.get(examExpertVo.getExpertId()+examExpertSettingParam.getSubjectId()).size());
                }
            }

        }
        if(MarkmodelEnums.MARK_MODEL_BATCH.getCode().equals(examExpertSettingParam.getMarkModel())
                && StringUtils.isNotEmpty(examExpertSettingParam.getBatchId())){

            taskWrapper.eq(Task :: getBatchId, examExpertSettingParam.getBatchId());
            //处理已评卷量逻辑
            Map<String,List<TaskNumberVo>> taskNumberMap = taskNumberVos.stream().collect(Collectors.groupingBy(c -> c.getExpertId() + c.getBatchId()));
            if(CollectionUtils.isNotEmpty(examExpertSettingVo.getExamExpertVos()) && MapUtils.isNotEmpty(taskNumberMap)) {
                for (ExamExpertVo examExpertVo : examExpertSettingVo.getExamExpertVos()) {
                    if(CollectionUtils.isEmpty(taskNumberMap.get(examExpertVo.getExpertId() + examExpertSettingParam.getBatchId()))){
                        continue;
                    }
                    examExpertVo.setAlreadyQuantity(taskNumberMap.get(examExpertVo.getExpertId() + examExpertSettingParam.getBatchId()).size());
                }
            }
        }
        if(MarkmodelEnums.MARK_MODEL_ROOM.getCode().equals(examExpertSettingParam.getMarkModel())
                && StringUtils.isNotEmpty(examExpertSettingParam.getRoomId())){
            taskWrapper.eq(Task :: getRoomId, examExpertSettingParam.getRoomId());
            //处理已评卷量逻辑
            Map<String,List<TaskNumberVo>> taskNumberMap = taskNumberVos.stream().collect(Collectors.groupingBy(c -> c.getExpertId() + c.getRoomId()));
            if(CollectionUtils.isNotEmpty(examExpertSettingVo.getExamExpertVos()) && MapUtils.isNotEmpty(taskNumberMap)) {
                for (ExamExpertVo examExpertVo : examExpertSettingVo.getExamExpertVos()) {
                    if(CollectionUtils.isEmpty(taskNumberMap.get(examExpertVo.getExpertId() + examExpertSettingParam.getRoomId()))){
                        continue;
                    }
                    examExpertVo.setAlreadyQuantity(taskNumberMap.get(examExpertVo.getExpertId() + examExpertSettingParam.getRoomId()).size());
                }
            }
        }
        
        Integer total = taskMapper.selectCount(taskWrapper);
        examExpertSettingVo.setMarkTotal(total);
        examExpertSettingVo.setTotalNumber(total);

        List<Task> tasks = taskMapper.selectList(taskWrapper);
        if(!CollectionUtils.isEmpty(tasks)){
            Set<String> pieceIds = tasks.stream().map(e -> e.getPieceId()).collect(Collectors.toSet());
            QueryWrapper<PieceScore> pieceScoreWrapper = new QueryWrapper<PieceScore>();
            pieceScoreWrapper.lambda().in(PieceScore :: getPieceId,pieceIds);
            Integer alreadyPaperTotal = pieceScoreMapper.selectCount(pieceScoreWrapper);
            examExpertSettingVo.setAlreadyPaperTotal(alreadyPaperTotal);
        }
        return examExpertSettingVo;
    }
	
	public List<ExpertTreeVo> queryExpertTreeVo(String officeId) {
		ApiResponse<List<Tree>> response = uaDeptService.getDeptTree();
		logger.info("## queryExpertTreeVo depttree:{}" , JSON.toJSON(response));
		List<ExpertTreeVo> expertTreeVos = new ArrayList<>();
		if (null == response || CollectionUtils.isEmpty(response.getData())) {
			logger.error("## 查询getDeptTree为空");
			return expertTreeVos;
		}
		String treeJson = JSON.toJSONString(response.getData());
		expertTreeVos = JSON.parseArray(treeJson, ExpertTreeVo.class);
		List<ExpertTreeVo> expertTreeVosTemp = new ArrayList<>();
		Map<String, ExpertUserVo> userMap = new HashMap<String, ExpertUserVo>();
		affiliationUsers(expertTreeVos, expertTreeVosTemp, userMap);
		return TreeUtil.treeToMultilevel(expertTreeVosTemp);
	}

	private void affiliationUsers(List<ExpertTreeVo> expertTreeVos, List<ExpertTreeVo> expertTreeVosTemp, Map<String, ExpertUserVo> userMap) {
		for (ExpertTreeVo expertTreeVo : expertTreeVos) {
			// 获取部门下所有专家角色人员
			List<ExpertTreeVo> child = expertTreeVo.getChildren();
			if (CollectionUtils.isNotEmpty(child)) {
				affiliationUsers(child, expertTreeVosTemp, userMap);
			}
			String deptId = expertTreeVo.getId();
			String roleCode = Constants.ROLECODE;
			List<ExpertUserVo> expertUserVos = getDeptAllUsers(deptId, roleCode);
			if (CollectionUtils.isNotEmpty(expertUserVos)) {
				List<ExpertUserVo> expertUserVoTemp = new ArrayList<ExpertUserVo>();
				for (Iterator<ExpertUserVo> iterator = expertUserVos.iterator(); iterator.hasNext();) {
					ExpertUserVo expertUserVo =  iterator.next(); 
					if(!userMap.containsKey(expertUserVo.getId())) {
						expertUserVoTemp.add(expertUserVo);
						userMap.put(expertUserVo.getId(), expertUserVo);
					}
				}
				expertTreeVo.setObj(expertUserVoTemp);
				expertTreeVo.setChildren(null);
				expertTreeVosTemp.add(expertTreeVo);
			}
		}
	}
    
	/****
	 * 获取当前部门以及子部门下面所有拥有角色权限的人
	 * 
	 * @param deptId
	 * @param roleId
	 * @return
	 */
	private List<ExpertUserVo> getDeptAllUsers(String deptId, String roleCode) {
		List<ExpertUserVo> expertUserVos = new ArrayList<ExpertUserVo>();
		int pageNum = 1;
		int pageSize = 100;
		boolean hasNext = true;
		while (hasNext) {
			OfficeUserPageParam officeUserPageParam = new OfficeUserPageParam();
			officeUserPageParam.setCurrent(pageNum);
			officeUserPageParam.setSize(pageSize);
			officeUserPageParam.setDeptId(deptId);
			officeUserPageParam.setRoleCode(roleCode);
			ApiResponse<Page<OfficeUserVO>> officeUserResponse = uaDeptService.getOfficeUserPage(officeUserPageParam);
			if (null != officeUserResponse && null != officeUserResponse.getData() && CollectionUtils.isNotEmpty(officeUserResponse.getData().getRecords())) {
				List<ExpertUserVo> expertUserVosTemp = new ArrayList<ExpertUserVo>();
				buildExpertUserVo(officeUserResponse.getData().getRecords(), expertUserVosTemp);
				expertUserVos.addAll(expertUserVosTemp);
				pageNum++;
			} else {
				hasNext = false;
			}
		}
		return expertUserVos;
	}


    private void buildExpertUserVo(List<OfficeUserVO> officeUserVOs,List<ExpertUserVo> expertUserVos){
        for (OfficeUserVO officeUserVO :officeUserVOs) {
            ExpertUserVo expertUserVo = new ExpertUserVo();
            expertUserVo.setDeptId(officeUserVO.getDeptId());
            expertUserVo.setDeptName(officeUserVO.getDeptName());
            expertUserVo.setId(officeUserVO.getId());
            expertUserVo.setName(officeUserVO.getName());
            expertUserVo.setPhone(officeUserVO.getPhone());
            expertUserVo.setStatus(officeUserVO.getStatus());
            expertUserVos.add(expertUserVo);
        }
    }


    @Override
    public List<ExpertTreeVo> queryOrganizationTree() {
        ApiResponse<List<Tree>> response = uaDeptService.getDeptTree();
        List<ExpertTreeVo> expertTreeVos = new ArrayList<>();
        if(null != response && !CollectionUtils.isEmpty(response.getData())) {
            String treeJson = JSON.toJSONString(response.getData());
            expertTreeVos = JSON.parseArray(treeJson, ExpertTreeVo.class);
        }
        return  expertTreeVos;
    }


    @Override
    public List<ExpertUserVo> queryOrganizationUsers(String deptId, Integer pageNum, Integer pageSize) {
        List<ExpertUserVo> expertUserVos = null;
        OfficeUserPageParam officeUserPageParam = new OfficeUserPageParam();
        officeUserPageParam.setDeptId(deptId);
        officeUserPageParam.setCurrent(pageNum);
        officeUserPageParam.setSize(pageSize);
        ApiResponse<Page<OfficeUserVO>> response = uaDeptService.getOfficeUserPage(officeUserPageParam);
        if(null != response && null != response.getData()
                && !CollectionUtils.isEmpty(response.getData().getRecords())){
            expertUserVos = new ArrayList<>();
            buildExpertUserVo(response.getData().getRecords(),expertUserVos);
        }

        return  expertUserVos;
    }


    @Override
    public Integer deleteExpertVo(String Id) {

        //已经提交评卷的专家不能删除
        ExamExpert examExpert = examExpertMapper.selectById(Id);
        ModeExpert modeExpert = modeExpertMapper.selectById(examExpert.getModeExpertId());
        QueryWrapper<ProjectSetting> projectSettingWrapper = new QueryWrapper<ProjectSetting>();
        projectSettingWrapper.lambda().eq(ProjectSetting :: getProjectId,modeExpert.getProjectId());
        List<ProjectSetting> projectSettings = projectSettingMapper.selectList(projectSettingWrapper);
        if(CollectionUtils.isEmpty(projectSettings)){
            return ResponseCode.PROJECT_SETTING_NOT_EMPTY;
        }
        //已发布不能删除专家
        Project project = projectMapper.selectById(projectSettings.get(0).getProjectId());
        if( CommonEnums.TASK_PUBLISH_STATUS_1.getCode().equals(project.getMarkPublish())){
            return ResponseCode.PUBLISH_TASK_NOT_EDIT;
        }
        //已开启自动分配任务，评卷专家人数不允许小于评卷次数，无法删除！
        if(MarkTypeEnums.MARK_TYPE_CROSS.getCode().equals(projectSettings.get(0).getMarkType()) && null != modeExpert.getAutoFlag()
                && AutoFlagEnums.AUTO_FlAG_OPEN.getCode() == modeExpert.getAutoFlag().intValue()){
            QueryWrapper<ExamExpert> examExpertWrapper = new QueryWrapper<ExamExpert>();
            examExpertWrapper.lambda().eq(ExamExpert :: getProjectId,modeExpert.getProjectId());
            Integer count = examExpertMapper.selectCount(examExpertWrapper);
            if(null != count && null != modeExpert.getNumber() && count.intValue() < modeExpert.getNumber()){
                return ResponseCode.OPEN_AUTOFLAG_NOT_DELETE;
            }
        }
        QueryWrapper<Task> taskWrapper = new QueryWrapper<Task>();
        taskWrapper.lambda().eq(Task :: getProjectId,modeExpert.getProjectId()).eq(Task :: getSubjectId,modeExpert.getSubjectId());
        List<Task> tasks = taskMapper.selectList(taskWrapper);
        if(!CollectionUtils.isEmpty(tasks)){
            Set<String> pieceIds = tasks.stream().map(e -> e.getPieceId()).collect(Collectors.toSet());
            QueryWrapper<PieceScore> pieceScoreWrapper = new QueryWrapper<PieceScore>();
            pieceScoreWrapper.lambda().eq(PieceScore :: getUserId,examExpert.getExpertId()).eq(PieceScore :: getFinish, CommonEnums.PIECCE_SCORE_FINSH_1.getCode())
                    .in(PieceScore :: getPieceId,pieceIds);
            Integer count = pieceScoreMapper.selectCount(pieceScoreWrapper);
            if(null != count && count.intValue()>0){
                return  ResponseCode.SUBMIT_TASK_NOT_DELETE;
            }
            pieceScoreWrapper = new QueryWrapper<>();
            pieceScoreWrapper.lambda().eq(PieceScore :: getUserId,examExpert.getExpertId()).in(PieceScore :: getPieceId,pieceIds);
            pieceScoreMapper.delete(pieceScoreWrapper);
            QueryWrapper<TeacherTaskInfo> teacherTaskInfoWrapper = new QueryWrapper<>();
            teacherTaskInfoWrapper.lambda().eq(TeacherTaskInfo :: getUserId,examExpert.getExpertId()).in(TeacherTaskInfo :: getPieceCode,pieceIds);
            teacherTaskInfoMapper.delete(teacherTaskInfoWrapper);

            QueryWrapper<ItemScore> itemScoreWrapper = new QueryWrapper<>();
            itemScoreWrapper.lambda().eq(ItemScore :: getUserId,examExpert.getExpertId()).in(ItemScore :: getPieceId,pieceIds);
            itemScoreMapper.delete(itemScoreWrapper);
        }
        examExpertMapper.deleteById(Id);
        return ResponseCode.SUCCESS;
    }


    @Override
    public List<ModeExamExpertVo> queryExamExpertVos(String projectId) {
        return examExpertMapper.queryExamExpertVos(projectId);

    }

    @Override
    public List<ModeExamExpertVo> queryEaxmModeExamExpertVos(String projectId,String subjectId,String batchId,String roomId) {
        return examExpertMapper.queryTaskExamExpertVos(projectId,subjectId,batchId,roomId);

    }


    @Override
    public String queryExpertBySubject(String projectId, String subjectId, String roomId, String markModel) {
        return examExpertMapper.queryExpertBySubject(projectId, subjectId, roomId, markModel);
    }

    @Override
    public List<ModeExamExpertVo> queryTaskExamExpertVos(String projectId) {
        return examExpertMapper.queryTaskExamExpertVos(projectId);
    }
}
